<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.5"/>
<title>libnetconf: transAPI Tutorial</title>
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<link href="../../navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../resize.js"></script>
<script type="text/javascript" src="../../navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
  $(window).load(resizeHeight);
</script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../libnetconf-logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">libnetconf
   &#160;<span id="projectnumber">0.7.0</span>
   </div>
   <div id="projectbrief">NETCONF Library</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.5 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="../../index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="../../pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="../../modules.html"><span>Modules</span></a></li>
      <li><a href="../../annotated.html"><span>Data&#160;Structures</span></a></li>
      <li><a href="../../files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="../../search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="../../search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('d3/df0/transapi_tutorial.html','../../');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(10)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">transAPI Tutorial </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>On this page we will show how to write a simple module for controlling <a href="http://netconfcentral.org/modulereport/toaster">example toaster</a>. </p>
<dl class="section note"><dt>Note</dt><dd>To install libnetconf follow the instructions on the <a class="el" href="../../d9/d87/install.html">Compilation and Installation</a> page.</dd></dl>
<h2>Preparations</h2>
<p>In this example we will work with the data model of the toaster provided by Andy Bierman at NETCONF CENTRAL (<a href="http://dld.netconfcentral.org/src/toaster@2009-11-20.yang">http://dld.netconfcentral.org/src/toaster@2009-11-20.yang</a>).</p>
<p>First, we need to identify important parts of the configuration data. Since the toaster data model describes only one configurable element, we have an easy choice. So, we can create the 'paths_file' file containing the specification of our chosen element and mapping prefixes with URIs for any used namespace.</p>
<p>Our file may look like this (irrespective of order): </p>
<div class="fragment"><div class="line">toaster=http:<span class="comment">//netconfcentral.org/ns/toaster</span></div>
<div class="line">/toaster:toaster</div>
</div><!-- fragment --><h2>Generating code</h2>
<ol type="1">
<li>Create a new directory for the toaster module and move the data model and the path file into it: <div class="fragment"><div class="line">$ mkdir toaster &amp;&amp; cd toaster/</div>
<div class="line">$ mv ../toaster@2009-11-20.yang ../paths_file .</div>
</div><!-- fragment --></li>
<li>Run `lnctool' for transapi: <div class="fragment"><div class="line">$ lnctool --model ./toaster@2009-11-20.yang <a class="code" href="../../d9/dc0/structtransapi.html">transapi</a> --paths ./paths_file</div>
</div><!-- fragment --></li>
</ol>
<p>Besides the generated source code of our transAPI module and GNU Build System files (Makefile.in, configure.in,...), lnctool also generates YIN format of the data model and validators accepted by the libnetconf's <a class="el" href="../../d8/d55/group__transapi.html#ga80e69b4cada8c35e5e358287e8af3d85" title="Create new datastore structure with transaction API support. ">ncds_new_transapi()</a> and <a class="el" href="../../db/d67/group__store.html#ga4777c16043f5856c5a65bcd20b5ecc31" title="Set validators (or disable validation) on the specified datastore. ">ncds_set_validation()</a> functions:</p>
<ul>
<li>*.yin - YIN format of the data model</li>
<li>*.rng - RelagNG schema for syntax validation</li>
<li>*-schematron.xsl - Schematron XSL stylesheet for semantics validation</li>
</ul>
<h2>Filling up functionality</h2>
<p>Here we show the simplest example of a toaster simulating module. It is working but does not deal with multiple access and threads correctly. Better example may can be found in the netopeer-server-sl source codes located in the <a href="https://code.google.com/p/netopeer">Netopeer project</a> repository (server-sl/toaster/toaster.c).</p>
<ol type="1">
<li>Open 'toaster.c' file with your favorite editor: <div class="fragment"><div class="line">$ vim toaster.c</div>
</div><!-- fragment --></li>
<li>Add global variables and auxiliary functions <div class="fragment"><div class="line"><span class="keyword">enum</span> {ON, OFF, BUSY} status;</div>
<div class="line">pthread_t thread;</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> * auxiliary_make_toast(<span class="keywordtype">void</span> * time)</div>
<div class="line">{</div>
<div class="line">        sleep(*(<span class="keywordtype">int</span>*)time);</div>
<div class="line"></div>
<div class="line">        <span class="keywordflow">if</span> (status == BUSY) {</div>
<div class="line">                status = ON;</div>
<div class="line">                <a class="code" href="../../da/d54/group__notifications.html#ga9641deaca934bcd7ff66ac3ae60fc722">ncntf_event_new</a>(-1, <a class="code" href="../../da/d54/group__notifications.html#ggadcf8c532762d57f7d9a5491e6abb9977a1f1e3c2032baf2542b06052243bd42c9">NCNTF_GENERIC</a>, <span class="stringliteral">&quot;&lt;toastDone&gt;&lt;toastStatus&gt;done&lt;/toastStatus&gt;&lt;/toastDone&gt;&quot;</span>);</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(NULL);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Complete the 'transapi_init()' function with actions that will be run right after the module loads and before any other function in the module is called. We ignore the XML document pointer, since we wish the toaster to be always off when loading this module. <div class="fragment"><div class="line"><span class="keywordtype">int</span> transapi_init(xmlDocPtr * running)</div>
<div class="line">{</div>
<div class="line">        status = OFF;</div>
<div class="line">        printf(<span class="stringliteral">&quot;Toaster initialized!\n&quot;</span>);</div>
<div class="line">        <span class="keywordflow">return</span>(EXIT_SUCCESS);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Locate the 'transapi_close()' function and fill it with actions that will be run just before the module unloads. No other function will be called after 'transapi_close()'. <div class="fragment"><div class="line"><span class="keywordtype">void</span> transapi_close()</div>
<div class="line">{</div>
<div class="line">        printf(<span class="stringliteral">&quot;Toaster ready for unplugging!\n&quot;</span>);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Fill 'get_state_data()' function with code that will generate state information as defined in the data model. <div class="fragment"><div class="line"><span class="keywordtype">char</span> * get_state_data(<span class="keywordtype">char</span> * model, <span class="keywordtype">char</span> * running, <span class="keyword">struct</span> nc_err **err)</div>
<div class="line">{</div>
<div class="line">        <span class="keywordflow">return</span> strdup(<span class="stringliteral">&quot;&lt;?xml version=&quot;</span>1.0<span class="stringliteral">&quot;?&gt;&lt;toaster xmlns=&quot;</span>http:<span class="comment">//netconfcentral.org/ns/toaster&quot;&gt; ... &lt;/toaster&gt;&quot;);</span></div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Complete the configuration callbacks. The 'op' parameter may be used to determine operation which was done with the node. Parameter 'node' holds a copy of node after change (or before change if op == XMLDIFF_REM). <div class="fragment"><div class="line"><span class="keywordtype">int</span> callback_toaster_toaster (<span class="keywordtype">void</span> ** data, <a class="code" href="../../d8/d55/group__transapi.html#ga10d59d84527f735d2781dbbb629a4488">XMLDIFF_OP</a> op, xmlNodePtr node, <span class="keyword">struct</span> nc_err** error)</div>
<div class="line">{</div>
<div class="line">        <span class="keywordflow">switch</span>(op) {</div>
<div class="line">        <span class="keywordflow">case</span> <a class="code" href="../../d8/d55/group__transapi.html#gga10d59d84527f735d2781dbbb629a4488adc0f4fc8354a1e293db5efd4f8e6f0b1">XMLDIFF_ADD</a>:</div>
<div class="line">                status = ON;</div>
<div class="line">                <span class="keywordflow">break</span>;</div>
<div class="line">        <span class="keywordflow">case</span> <a class="code" href="../../d8/d55/group__transapi.html#gga10d59d84527f735d2781dbbb629a4488a149cdeec9d87bdbb700861f773759129">XMLDIFF_REM</a>:</div>
<div class="line">                status = OFF;</div>
<div class="line">                <span class="keywordflow">break</span>;</div>
<div class="line">        <span class="keywordflow">default</span>:</div>
<div class="line">                *error = <a class="code" href="../../d3/d35/group__gen_a_p_i.html#ga057524ba5256c428b6bf88710f000e0c">nc_err_new</a>(<a class="code" href="../../da/d41/error_8h.html#a170ed93037b65394a05e074400848eb2ae9d2e7a938b0fb4583b961a7079aabe3">NC_ERR_OP_FAILED</a>);</div>
<div class="line">                <a class="code" href="../../d3/d35/group__gen_a_p_i.html#gab28d881eeebd79d485391ae1ffc97299">nc_err_set</a>(*error, <a class="code" href="../../d3/d7a/netconf_8h.html#a39c5f77f5cf9108a27e7a65f3b2ba73da1695230cad67458870f4cf93a2d530a5">NC_ERR_PARAM_MSG</a>, <span class="stringliteral">&quot;Unsupported operation.&quot;</span>);</div>
<div class="line">                <span class="keywordflow">return</span>(EXIT_FAILURE);</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(EXIT_SUCCESS);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Fill the RPC message callback functions with code that will be run when a message arrives. <div class="fragment"><div class="line"><a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d">nc_reply</a> * rpc_make_toast (xmlNodePtr input[])</div>
<div class="line">{</div>
<div class="line">        xmlNodePtr toasterDoneness = input[0];</div>
<div class="line">        xmlNodePtr toasterToastType = input[1];</div>
<div class="line"></div>
<div class="line">        <a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d">nc_reply</a> * reply;</div>
<div class="line">        <span class="keywordtype">int</span> doneness = atoi(xmlNodeGetContent(toasterDoneness));</div>
<div class="line"></div>
<div class="line">        <span class="keywordflow">if</span> (status == ON) {</div>
<div class="line">                status = BUSY;</div>
<div class="line">                pthread_create(&amp;thread, NULL, auxiliary_make_toast, (<span class="keywordtype">void</span>*)&amp;doneness);</div>
<div class="line">                pthread_detach(thread);</div>
<div class="line">                reply = <a class="code" href="../../d0/de2/group__reply.html#ga047f565bb3671ec4016fef5461e8f67e">nc_reply_ok</a>();</div>
<div class="line">        } <span class="keywordflow">else</span> {</div>
<div class="line">                reply = <a class="code" href="../../d0/de2/group__reply.html#ga12fd89263289491b84398279e0e449fd">nc_reply_error</a>(<a class="code" href="../../d3/d35/group__gen_a_p_i.html#ga057524ba5256c428b6bf88710f000e0c">nc_err_new</a>(<a class="code" href="../../da/d41/error_8h.html#a170ed93037b65394a05e074400848eb2ae9d2e7a938b0fb4583b961a7079aabe3">NC_ERR_OP_FAILED</a>));</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(reply);</div>
<div class="line">}</div>
</div><!-- fragment --> <div class="fragment"><div class="line"><a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d">nc_reply</a> * rpc_cancel_toast (xmlNodePtr input[])</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d">nc_reply</a> * reply;</div>
<div class="line"></div>
<div class="line">        <span class="keywordflow">if</span> (status == BUSY) {</div>
<div class="line">                status = ON;</div>
<div class="line">                <a class="code" href="../../da/d54/group__notifications.html#ga9641deaca934bcd7ff66ac3ae60fc722">ncntf_event_new</a>(-1, <a class="code" href="../../da/d54/group__notifications.html#ggadcf8c532762d57f7d9a5491e6abb9977a1f1e3c2032baf2542b06052243bd42c9">NCNTF_GENERIC</a>, <span class="stringliteral">&quot;&lt;toastDone&gt;&lt;toastStatus&gt;canceled&lt;/toastStatus&gt;&lt;/toastDone&gt;&quot;</span>);</div>
<div class="line">                reply = <a class="code" href="../../d0/de2/group__reply.html#ga047f565bb3671ec4016fef5461e8f67e">nc_reply_ok</a>();</div>
<div class="line">        } <span class="keywordflow">else</span> {</div>
<div class="line">                reply = <a class="code" href="../../d0/de2/group__reply.html#ga12fd89263289491b84398279e0e449fd">nc_reply_error</a>(<a class="code" href="../../d3/d35/group__gen_a_p_i.html#ga057524ba5256c428b6bf88710f000e0c">nc_err_new</a>(<a class="code" href="../../da/d41/error_8h.html#a170ed93037b65394a05e074400848eb2ae9d2e7a938b0fb4583b961a7079aabe3">NC_ERR_OP_FAILED</a>));</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(reply);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
</ol>
<h2>Compiling module</h2>
<p>Following sequence of commands will produce the shared library 'toaster.so' which may be loaded into libnetconf: </p>
<div class="fragment"><div class="line">$ autoreconf</div>
<div class="line">$ ./configure</div>
<div class="line">$ make</div>
</div><!-- fragment --><h2>Integrating to a server</h2>
<p>In a server we use libnetconf's function <a class="el" href="../../d8/d55/group__transapi.html#ga80e69b4cada8c35e5e358287e8af3d85" title="Create new datastore structure with transaction API support. ">ncds_new_transapi()</a> instead of <a class="el" href="../../db/d67/group__store.html#ga69009c5985f9eec3a6920f98a6a1a5e6" title="Create a new datastore structure of the specified implementation type. ">ncds_new()</a> to create a transAPI-capable data store. Then, you do not need to process any data-writing (edit-config, copy-config, delete-config, lock, unlock), data-reading (get, get-config) or module data-model-defined RPC operations. All these operations are processed inside the <a class="el" href="../../db/d67/group__store.html#ga6e6e979bd82e50913c82b4dc37cb8759" title="Perform the requested RPC operation on the all datastores controlled by the libnetconf (created by nc...">ncds_apply_rpc2all()</a> function. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="../../d9/d25/transapi.html">Transaction API (transAPI)</a></li>
    <li class="footer">Generated on Thu Feb 6 2014 16:01:55 for libnetconf by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="../../doxygen.png" alt="doxygen"/></a> 1.8.5 </li>
  </ul>
</div>
</body>
</html>
